﻿
using UnityEngine;
using System.IO;
using System.Text.RegularExpressions;
using System;
using System.Reflection;


namespace GersonFrame.Tool
{

    public class MyDebuger
    {
        private static string fullPath;

        private static bool m_hasForceMono = false;
        public static void InitLogger()
        {
            fullPath = Application.dataPath + "/output.txt";
            if (File.Exists(fullPath)) File.Delete(fullPath);
            if (Directory.Exists(fullPath.Replace("/output.txt", "")))
            {
                FileStream fs = File.Create(fullPath);
                fs.Close();
                Application.logMessageReceived += logCallBack;
            }
            else
            {
                MyDebuger.LogError("directory is not exist");
            }
        }

        private static void logCallBack(string condition, string stackTrace, LogType type)
        {
            if (File.Exists(fullPath))
            {
                using (StreamWriter sw = File.AppendText(fullPath))
                {
                    sw.WriteLine(condition);
                    sw.WriteLine(stackTrace);
                }
            }
        }


        private static bool UseLog = true;


        public static void SetUseDebuger(bool use)
        {
            UseLog = use;
        }

        #region Debuge

        public static void Log(object message)
        {
            if (UseLog) Debug.Log("[MyLog]" + message);
        }

        public static void Log(object message, UnityEngine.Object context)
        {
            if (UseLog) Debug.Log("[MyLog]" + message, context);
        }

        public static void LogError(object message)
        {
            Debug.LogError("[MyLog]" + message);
        }

        public static void LogError(object message, UnityEngine.Object context)
        {
            Debug.LogError("[MyLog]" + message, context);
        }

        public static void LogErrorFormat(string format, params object[] args)
        {
            Debug.LogErrorFormat("[MyLog]" + format, args);
        }

        public static void LogErrorFormat(UnityEngine.Object context,
            string format, params object[] args)
        {
            Debug.LogErrorFormat("[MyLog]" + context, format, args);
        }





        public static void LogFormat(string format, params object[] args)
        {
            if (UseLog) Debug.LogFormat("[MyLog]" + format, args);
        }

        public static void LogFormat(UnityEngine.Object context,
            string format, params object[] args)
        {
            if (UseLog) Debug.LogFormat("[MyLog]" + context, format, args);
        }

        public static void LogWarning(object message)
        {
            if (UseLog) Debug.LogWarning("[MyLog]" + message);
        }

        public static void LogWarning(object message,
            UnityEngine.Object context)
        {
            if (UseLog) Debug.LogWarning("[MyLog]" + message, context);
        }

        public static void LogWarningFormat(string format,
            params object[] args)
        {
            if (UseLog) Debug.LogWarningFormat("[MyLog]" + format, args);
        }

        public static void LogWarningFormat(UnityEngine.Object context,
            string format, params object[] args)
        {
            if (UseLog) Debug.LogWarningFormat("[MyLog]" + context, format, args);
        }
        #endregion

        #region Editor
#if UNITY_EDITOR
        // 处理asset打开的callback函数
        [UnityEditor.Callbacks.OnOpenAssetAttribute(-1)]
        static bool OnOpenAsset(int instance, int line)
        {
            if (m_hasForceMono) return false;

            // 自定义函数，用来获取log中的stacktrace，定义在后面。
            string stack_trace = GetStackTrace();
            // 通过stacktrace来定位是否是我们自定义的log，我的log中有特殊文字[SDebug]，很好识别
            if (!string.IsNullOrEmpty(stack_trace) && stack_trace.Contains("[MyLog]"))
            {
                // 正则匹配at xxx，在第几行
                Match matches = Regex.Match(stack_trace, @"\(at (.+)\)", RegexOptions.IgnoreCase);
                string pathline = "";
                while (matches.Success)
                {
                    pathline = matches.Groups[1].Value;

                    // 找到不是我们自定义log文件的那行，重新整理文件路径，手动打开
                    if (!pathline.Contains("MyDebuger.cs") && !string.IsNullOrEmpty(pathline))
                    {
                        int split_index = pathline.LastIndexOf(":");
                        string path = pathline.Substring(0, split_index);
                        line = Convert.ToInt32(pathline.Substring(split_index + 1));
                        m_hasForceMono = true;
                        //方式一
                        UnityEditor.AssetDatabase.OpenAsset(UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path), line);
                        m_hasForceMono = false;
                        //方式二
                        //string fullpath = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("Assets"));
                        // fullpath = fullpath + path;
                        //  UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(fullpath.Replace('/', '\\'), line);
                        return true;
                    }
                    matches = matches.NextMatch();
                }
                return true;
            }
            return false;
        }


        static string GetStackTrace()
        {
            // 找到类UnityEditor.ConsoleWindow
            var type_console_window = typeof(UnityEditor.EditorWindow).Assembly.GetType("UnityEditor.ConsoleWindow");
            // 找到UnityEditor.ConsoleWindow中的成员ms_ConsoleWindow
            var filedInfo = type_console_window.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
            // 获取ms_ConsoleWindow的值
            var ConsoleWindowInstance = filedInfo.GetValue(null);
            if (ConsoleWindowInstance != null)
            {
                if ((object)UnityEditor.EditorWindow.focusedWindow == ConsoleWindowInstance)
                {
                    // 找到类UnityEditor.ConsoleWindow中的成员m_ActiveText
                    filedInfo = type_console_window.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
                    string activeText = filedInfo.GetValue(ConsoleWindowInstance).ToString();
                    return activeText;
                }
            }
            return null;
        }
#endif
        #endregion

    }
}